<script lang="ts">
    import {bem} from "@/common/util";
    import mixin from "@/uni_modules/u-tools/mixin/mixin";
    import mpMixin from "@/uni_modules/u-tools/mixin/mpMixin";
    import props from "./props";
    import ULoadingIcon from "@/uni_modules/u-loading-icon/components/u-loading-icon/u-loading-icon.vue";

    export default {
        name: "u-switch",
        // 组件
        components: {ULoadingIcon},
        // 混合
        mixins: [props, mixin, mpMixin],
        // 事件
        emits: ["change", "update:value", "onload"],
        // 数据
        data()
        {
            return {
                // 选中状态
                status: false
            };
        },
        // 监听器
        watch: {
            // 监听value的变化
            value(value: boolean): void
            {
                this.status = value;
            }
        },
        // 页面挂载
        mounted()
        {
            // 组件挂载完成
            this.$nextTick(() =>
            {
                // 获取当前单选框的值
                this.status = this.value;

                // 判断是否触发change事件
                if (this.trigger)
                {
                    // 触发自定义change事件
                    this.$emit("change", this.status);
                }

                // 触发onload事件
                this.$emit("onload", this.status);
            });
        },
        // 计算函数
        computed: {
            // 生成bem风格的类名
            bemClass(): string
            {
                return bem("switch", [
                    this.status ? "active" : "",
                    this.disabled ? "disabled" : ""
                ]);
            },
            // 获取开关的样式
            getSwitchStyle(): Record<string, any>
            {
                const style: Record<string, any> = {
                    width: this.$u.unit(parseFloat(this.size.toString()) * 2),
                    height: this.$u.unit(parseFloat(this.size.toString()) + 1),
                    backgroundColor: this.status ? this.activeColor : this.inactiveColor
                };

                // 判断是否为自定义选中颜色
                if (!["#fff", "#fff"].includes(this.inactiveColor.toLocaleLowerCase()))
                {
                    style.borderColor = "rgba(0, 0, 0, 0)";
                }

                return style;
            },
            // 获取背景的样式
            getBackgroundStyle(): Record<string, any>
            {
                return {
                    width: this.$u.unit(parseFloat(this.size.toString()) * 2 - parseFloat(this.size.toString()) / 2),
                    height: this.$u.unit(this.size),
                    backgroundColor: this.inactiveColor,
                    transform: `scale(${this.status ? 0 : 1})`
                };
            },
            // 获取块的样式
            getNodeStyle(): Record<string, any>
            {
                return {
                    width: this.$u.unit(parseFloat(this.size.toString()) - parseFloat(this.space.toString()) * 2),
                    height: this.$u.unit(parseFloat(this.size.toString()) - parseFloat(this.space.toString()) * 2),
                    transform: `translateX(-${this.status ? this.$u.unit(this.space) : this.$u.unit(this.size)})`
                };
            }
        },
        // 方法
        methods: {
            // 改变事件
            changeHandler(event: Record<string, any>): void
            {
                // 禁用默认行为事件
                this.stopPropagation(event);

                // 禁用或则Loading
                if (this.disabled || this.loading)
                {
                    return;
                }

                // 判断是否异步
                if (!this.async)
                {
                    // 切换状态
                    this.status = !this.status;

                    // 触发change事件
                    this.$emit("change", this.status);

                    // 触发双向绑定事件
                    this.$emit("update:value", this.status);
                }
                else
                {
                    // 触发change事件
                    this.$emit("change", this.status);
                }

                // 阻止冒泡
                this.stop && this.stopPropagation(event);

                // 阻止事件默认行为
                this.prevent && this.preventDefault(event);
            }
        }
    };
</script>

<template>
    <!-- 开关组件 -->
    <view
        :class="[
            bemClass,
            customClass
        ]"
        :name="name"
        :style="[
            customStyle,
            getSwitchStyle
        ]"
        @tap.stop="changeHandler"
    >
        <!-- 背景 -->
        <view
            :style="getBackgroundStyle"
            class="u-switch-bg"
        />
        <!-- //背景 -->

        <!-- 块 -->
        <view
            :style="getNodeStyle"
            class="u-switch-node"
        >
            <u-loading-icon
                :color="status ? activeColor : '#8e8e8e'"
                :show="loading"
                :size="parseFloat(size.toString()) * 0.6"
                mode="circle"
            />
        </view>
        <!-- //块 -->
    </view>
    <!-- //开关组件 -->
</template>

<style lang="scss" scoped>
    $u-switch-border-color: rgba(0, 0, 0, 0.12) !default;

    .u-switch
    {
        position: relative;
        display: flex;
        overflow: hidden;
        align-items: center;
        justify-content: flex-end;
        box-sizing: border-box;
        transition-duration: .4s;
        transition-property: background-color;
        border: 1px solid $u-switch-border-color;
        border-radius: 100px;
        flex-direction: row;

        // 背景
        &-bg
        {
            position: absolute;
            transition-timing-function: ease;
            transition-duration: .4s;
            transition-property: transform;
            border-radius: 0 100px 100px 0;
        }

        // 块
        &-node
        {
            position: relative;
            display: flex;
            align-items: center;
            justify-content: center;
            transition-timing-function: cubic-bezier(0.3, 1.05, 0.4, 1.05);
            transition-duration: .4s;
            transition-property: transform;
            border-radius: 100px;
            background-color: #fff;
            box-shadow: 1px 1px 1px 0 rgba(0, 0, 0, 0.25);
        }

        // 禁用
        &-disabled
        {
            cursor: not-allowed;
            opacity: 0.5;
        }
    }
</style>